[GitHub Actions] ブランチごとにジョブの実行を制御できる Environments を試してみた
こんにちは、CX事業本部 Delivery部の若槻です。
今回は、GitHub Actions でブランチごとにジョブの実行を制御できる Environments を試してみました。
Environments とは
Environments とは、リポジトリごとに作成した Environment に対して、デプロイメントの保護規則や variable、secret を設定できる GitHub Actions の機能です。
Environments で提供されている機能は大きく分けて次の7つとなります。
- Deployment protection rules(デプロイ保護規則)
- Required reviewers(必須のレビュー担当者)
- Wait timer(待機タイマー)
- Deployment branches(デプロイメントブランチ)
- Allow administrators to bypass configured protection rules(構成された保護規則を管理者がバイパスすることを許可する)
- Custom deployment protection rules(カスタム デプロイ保護規則)
- Environment secrets(環境シークレット)
- Environment variables(環境変数)
各機能ごとに必要なプランは以下のようになります。パブリックリポジトリでは全ての機能が使用できますが、プライベートリポジトリではプランによって使用できる機能が異なります。
機能 | プライベートリポジトリ | パブリックリポジトリ |
---|---|---|
Required reviewers | GitHub Enterprise | Free 以上 |
Wait timer | GitHub Enterprise | Free 以上 |
Deployment branches | GitHub Pro または GitHub Team 以上 | Free 以上 |
Allow administrators to bypass configured protection rules | GitHub Enterprise | Free 以上 |
Custom deployment protection rules | GitHub Enterprise | Free 以上 |
Environment secrets | GitHub Pro または GitHub Team 以上 | Free 以上 |
Environment variables | GitHub Pro または GitHub Team 以上 | Free 以上 |
今回は、GitHub Pro または GitHub Team 以上のプランで利用できる次の3機能を試してみます。これらの機能により、Environment ごとに異なるブランチを対応付けて、ブランチごとに実行させるジョブや、参照させる secrets および variables を制御することができます。
- Deployment branches
- Environment secrets
- Environment variables
試してみた
GitHub Team のアカウントで試していきます。
Environment の作成
リポジトリの Settings > Environments より Environments のメニューを開きます。(必要なプランでない場合はメニューは表示されません)
New environment をクリックします。
Environment の名前を指定し、Configure environment をクリックして Environment を作成します。
作成できました。このメニューで Environment の設定を行います。
Deployment branches の設定
まず Deployment branches を設定します。今回は Selected branches
を選択します。
Deployment branches の Add deployment branch rule をクリックします。
ルールを適用するブランチのパターンを指定します。ここでは develop
を指定し、develop
というブランチでのみこの Environment が使われるようにします。
Deployment branches でルールを追加できました。
Environment secrets の設定
Environment secrets の値は作成後に暗号化され、GitHub Actions のコンテキストからのみアクセスできるようになります。APIキーなどの機密データを保存するのに適しています。
Environment secrets の Add secret をクリックします。
secret の名前および値を指定して、Add secret をクリックします。
HOGE_SECRET
という名前で secret を追加できました。
Environment variables の設定
Environment variables の値は作成後にもメニューから参照することができ、センシティブでないデータを保存するのに適しています。
Environment variables の Add variable をクリックします。
variable の名前および値を指定して、Add variable をクリックします。
HOGE_VARIABLE
という名前で variable を追加できました。
Environment をさらに追加
さらに、staging
および main
ブランチに対応した Environment を追加します。
これで development
、staging
および main
の3つのブランチに対応した Environment が作成できました。
動作確認
ワークフローでは、jobs.<job_id>.environment
に Environment の名前を指定することで、その Environment のルールの適用や、Environment secrets および Environment variables の参照が可能になります。
今回は次のようなワークフローを作成しました。dev_deployment
、stg_deployment
および prod_deployment
のジョブは、integration
ジョブ後に並行して実行されるようにしています。
on: push: branches: - develop - staging - main jobs: integration: runs-on: ubuntu-latest steps: - name: integration run: | echo "Integration" dev_deployment: runs-on: ubuntu-latest if: github.ref_name == 'develop' environment: development # Environment の名前を指定 needs: integration steps: - name: deploy run: | echo "Development Deployment" echo ${{ vars.HOGE_ENV }} echo ${{ secrets.HOGE_SECRET }} stg_deployment: runs-on: ubuntu-latest if: github.ref_name == 'staging' environment: staging # Environment の名前を指定 needs: integration steps: - name: deploy run: | echo "Staging Deployment" echo ${{ vars.HOGE_ENV }} echo ${{ secrets.HOGE_SECRET }} prod_deployment: runs-on: ubuntu-latest if: github.ref_name == 'main' environment: production # Environment の名前を指定 needs: integration steps: - name: deploy run: | echo "Production Deployment" echo ${{ vars.HOGE_ENV }} echo ${{ secrets.HOGE_SECRET }}
Pull Request のマージなどによる main
ブランチへの push が行われると、Deployment branche で main
を指定している production
Environment のジョブのみ実行されました。
ジョブの実行内容を見ると、main
ブランチに対応した Environment の variable および secret が参照されていることが分かります。
また、Environment ごとの最後に実行された Deployment のステータスがリポジトリトップページに表示されます。
アクセスすると Deployment の履歴が確認できます。これは GitHub Actions とは異なる UI となっています。
Environment ごとの履歴も確認できます。
ポイントおよび注意点
Environments を使うにあたりいくつかポイントや注意点がありました。
ref による実行条件により、ブランチルールを満たさないジョブを実行させないようにする必要がある
前述のワークフローでは、if: github.ref_name == 'branch_name'
という条件を使用することで、ブランチルールを満たさないジョブを実行させないようにしています。
検証として、次のように実行条件を指定しないワークフローを試してみます。
on: push: branches: - develop - staging - main jobs: integration: runs-on: ubuntu-latest steps: - name: integration run: | echo "Integration" dev_deployment: runs-on: ubuntu-latest # if: github.ref_name == 'develop' environment: development needs: integration steps: - name: deploy run: | echo "Development Deployment" echo ${{ vars.HOGE_ENV }} echo ${{ secrets.HOGE_SECRET }} stg_deployment: runs-on: ubuntu-latest # if: github.ref_name == 'staging' environment: staging needs: integration steps: - name: deploy run: | echo "Staging Deployment" echo ${{ vars.HOGE_ENV }} echo ${{ secrets.HOGE_SECRET }} prod_deployment: runs-on: ubuntu-latest # if: github.ref_name == 'main' environment: production needs: integration steps: - name: deploy run: | echo "Production Deployment" echo ${{ vars.HOGE_ENV }} echo ${{ secrets.HOGE_SECRET }}
main
ブランチへの push を行うと、main
ブランチに対応したジョブの実行は成功しましたが、 develop
および staging
Environment に対応したジョブは失敗しています。
Branch "main" is not allowed to deploy to development due to environment protection rules. The deployment was rejected or didn't satisfy other protection rules.
指定のブランチへの push 時に行いたいジョブ実行は行われますが、ワークフローの実行自体は失敗してしまうため、ref による実行条件により ブランチルールを満たさない Environment のジョブを実行させないようにする必要がありました。
レビューによりワークフローを進めるためには GitHub Enterprise が必要
本来であれば develop -> staging -> main
という順番で、前段の Environment へのデプロイ後に、人間によるレビューを経て次の Environment へのデプロイを行いたいところですが、承認によりワークフローを進めるには GitHub Enterprise 以上で使える「Required reviewers」機能が必要となります。
レビューを想定した場合のワークフローとしては次のようになります。stg_deployment
および prod_deployment
で前段のデプロイのジョブを指定します。
on: push: branches: - develop - staging - main jobs: integration: runs-on: ubuntu-latest steps: - name: integration run: | echo "Integration" dev_deployment: runs-on: ubuntu-latest environment: development needs: integration steps: - name: deploy run: | echo "Development Deployment" echo ${{ vars.HOGE_ENV }} echo ${{ secrets.HOGE_SECRET }} stg_deployment: runs-on: ubuntu-latest environment: staging needs: dev_deployment # 前段のデプロイのジョブを指定 steps: - name: deploy run: | echo "Staging Deployment" echo ${{ vars.HOGE_ENV }} echo ${{ secrets.HOGE_SECRET }} prod_deployment: runs-on: ubuntu-latest environment: production needs: stg_deployment # 前段のデプロイのジョブを指定 steps: - name: deploy run: | echo "Production Deployment" echo ${{ vars.HOGE_ENV }} echo ${{ secrets.HOGE_SECRET }}
するとワークフローは一直線となりますが、レビューの要求を設定していないブランチルールだと、ブランチパターンにマッチせず、ジョブが失敗します。
よって GitHub Enterprise でないアカウントの場合は、上述の直列ではなく、最初に試したような並行な形式のワークフローを組む必要があります。
pull_request トリガーの場合は、ヘッドブランチ(マージ元)が Environment で使われる
次のように pull_request トリガーのワークフローの場合、ヘッドブランチ(マージ元)が Environment で使われる挙動となりました。(つまり github.base_ref
ではなく github.head_ref
が使われる)
on: pull_request: types: - closed jobs: integration: runs-on: ubuntu-latest steps: - name: integration run: | echo "Integration" dev_deployment: runs-on: ubuntu-latest if: github.base_ref == 'develop' environment: development needs: integration steps: - name: deploy run: | echo "Development Deployment" echo ${{ vars.HOGE_ENV }} echo ${{ secrets.HOGE_SECRET }} stg_deployment: runs-on: ubuntu-latest if: github.base_ref == 'staging' environment: staging needs: integration steps: - name: deploy run: | echo "Staging Deployment" echo ${{ vars.HOGE_ENV }} echo ${{ secrets.HOGE_SECRET }} prod_deployment: runs-on: ubuntu-latest if: github.base_ref == 'main' environment: production needs: integration steps: - name: deploy run: | echo "Production Deployment" echo ${{ vars.HOGE_ENV }} echo ${{ secrets.HOGE_SECRET }}
feature ブランチから develop
ブランチへ Pull Request のマージをしてみます。
すると、develop
ブランチに対応した Environment のジョブが実行されますが、失敗してしまいます。
エラーメッセージによるとヘッドブランチ(マージ元)が Environment で使われているため、ブランチルールにマッチせず、ジョブが失敗してしまっています。
Branch "cm-rwakatsuki-patch-1" is not allowed to deploy to development due to environment protection rules.
同じ Pull Request のマージによるワークフロー実行でも、push と pull_request では使用されるブランチが異なるため、注意が必要です。
おわりに
GitHub Actions でブランチごとにジョブの実行を制御できる Environments を試してみました。
Pull Request マージなどが行われたブランチごとに異なる Environment に対応したジョブを実行させたり、secret および variable を参照させたりすることができることが確認できました。今回は GitHub Team の環境で試したましたが、GitHub Enterprise を使用すれば更に柔軟なワークフローを組むこともできます。
ただしブランチごとにジョブの実行内容を、参照させる secret や variable 以外に変える必要が無い場合は、ジョブの記述が重複して冗長となるため、次のようなブランチごとに参照先を変更する方法をとっても良さそうです。
参考
以上